package com.tencent.wepay.protocol.http;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tencent.wepay.spi.WepayRepository;

public class HttpsRequest{
	private static Logger logger=LoggerFactory.getLogger(HttpsRequest.class);
	private final static Map<String,CloseableHttpClient> httpClientCache=new HashMap<String,CloseableHttpClient>();
	//连接超时时间，默认10秒
    private static int socketTimeout = 10000;

    //传输超时时间，默认30秒
    private static int connectTimeout = 30000;
    
    private static RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
    	
    private static HttpsRequest request=null;
    private HttpsRequest() {
    	
    }
    public static HttpsRequest getInstance() {  
        if (request == null) {    
            synchronized (HttpsRequest.class) {    
               if (request == null) {    
                  request = new HttpsRequest();   
               }    
            }    
        }    
        return request;   
    }  
    private CloseableHttpClient getClientAndCache(WepayRepository repository){
    	FileInputStream instream=null;
		try {
			instream = new FileInputStream(new File(repository.getPath()));// 加载本地的证书进行https加密传输
			
	        KeyStore keyStore = KeyStore.getInstance("PKCS12");
			keyStore.load(instream, repository.getPassword().toCharArray());// 设置证书密码
			SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,
					repository.getPassword().toCharArray()).build();
			// Allow TLSv1 protocol only
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
			sslcontext, new String[] { "TLSv1" }, null,
			SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			CloseableHttpClient httpClient=HttpClients.custom().setMaxConnTotal(200).setMaxConnPerRoute(20).setSSLSocketFactory(sslsf).setRetryHandler(new DefaultHttpRequestRetryHandler()).build();
			httpClientCache.put(repository.getAppid(), httpClient);
			return httpClient;
		} catch (Exception e) {
			logger.error("certificate load error");
		} finally {
			try {
				if(instream!=null)
					instream.close();
			} catch (IOException e) {
				
			}
		}
		return null;
    }
		
	public String post(String url, String content,WepayRepository repository) throws Exception {
    	return post(url, content, ContentType.create("text/xml",Consts.UTF_8),repository);

	}

	public String post(String url, String content, ContentType contentType,WepayRepository repository) throws Exception {
		CloseableHttpClient httpClient=httpClientCache.get(repository.getAppid());
		if(httpClient==null){
			httpClient=getClientAndCache(repository);
		}
		logger.debug("request content:"+content);
		HttpPost httpPost=new HttpPost(url);
		httpPost.setConfig(requestConfig);
        httpPost.addHeader("Content-Type",ContentType.TEXT_XML.getMimeType());
		StringEntity postEntity=null;
		try {
			postEntity = new StringEntity(content, "UTF-8");
			httpPost.setEntity(postEntity);	
		    HttpResponse response = httpClient.execute(httpPost);
		    HttpEntity entity = response.getEntity();
		    return EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) {
			logger.error(url+",send ssl request error",e);
			throw e;
		}
    }
}
